const express = require('express');
const Mock = require('mockjs');
const fs = require('fs');
const path = require('path');
const chokidar = require('chokidar');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3000;

// Store loaded mock configurations
const mockConfigs = new Map();

// Function to load mock configurations from a directory
function loadMockConfigs(directory) {
    const configPath = path.resolve(directory);
    if (!fs.existsSync(configPath)) {
        console.log(`Directory ${configPath} does not exist`);
        return;
    }

    // Clear existing configurations
    mockConfigs.clear();

    // Function to process a directory
    function processDirectory(dir) {
        const items = fs.readdirSync(dir);
        
        items.forEach(item => {
            const itemPath = path.join(dir, item);
            const stat = fs.statSync(itemPath);
            
            if (stat.isDirectory()) {
                // Recursively process subdirectories
                processDirectory(itemPath);
            } else if (item.endsWith('.js')) {
                try {
                    // Use require to load the mock template
                    const template = require(itemPath);
                    const relativePath = path.relative(configPath, itemPath);
                    const routePath = relativePath.replace(/\\/g, '/').replace('.js', '');
                    mockConfigs.set(routePath, template);
                    console.log(`Loaded mock configuration for ${routePath}`);
                } catch (error) {
                    console.error(`Error loading mock configuration from ${itemPath}:`, error);
                }
            }
        });
    }

    processDirectory(configPath);
}

// Function to watch for changes in mock configurations
function watchMockConfigs(directory) {
    const watcher = chokidar.watch(directory, {
        ignored: /(^|[\/\\])\../,
        persistent: true
    });

    watcher
        .on('add', path => {
            console.log(`File ${path} has been added`);
            // Clear require cache to reload the module
            Object.keys(require.cache).forEach(key => {
                if (key.startsWith(directory)) {
                    delete require.cache[key];
                }
            });
            loadMockConfigs(directory);
        })
        .on('change', path => {
            console.log(`File ${path} has been changed`);
            // Clear require cache to reload the module
            Object.keys(require.cache).forEach(key => {
                if (key.startsWith(directory)) {
                    delete require.cache[key];
                }
            });
            loadMockConfigs(directory);
        })
        .on('unlink', path => {
            console.log(`File ${path} has been removed`);
            loadMockConfigs(directory);
        });
}

// Middleware to handle mock requests
app.use((req, res, next) => {
    const routePath = req.path.slice(1); // Remove leading slash
    const mockConfig = mockConfigs.get(routePath);

    if (mockConfig) {
        const mockData = Mock.mock(mockConfig);
        res.json(mockData);
    } else {
        next();
    }
});

// Load initial mock configurations
const mockDir = process.env.MOCK_DIR || path.join(__dirname, '../mocks');
loadMockConfigs(mockDir);
watchMockConfigs(mockDir);

app.listen(PORT, () => {
    console.log(`Mock server is running on port ${PORT}`);
    console.log(`Watching mock configurations in ${mockDir}`);
}); 